﻿// 随机数生成

using System;
using System.Collections.Generic;
using static AdjPlane.Angle_t;

namespace AdjPlane
{
    public partial class Plane
    {
        /// <summary>
        /// 添加误差
        /// </summary>
        /// <param name="count">添加随机数的次数，最后取均值</param>
        /// <param name="le">添加方向误差</param>
        /// <param name="sa">添加固定误差</param>
        /// <param name="sb">添加比例误差</param>
        void AddError(int count, double le, double sa, double sb)
        {
            M0 += le;//验前中误差也要随之改变
            double[] A = Rand.GetRand2(count, nl, 0, le);
            var X = new Dictionary<string, List<string>>();
            foreach (KeyValuePair<string, Dictionary<string, double>> sta in obsL)
            {
                List<string> x = new List<string>();
                foreach (KeyValuePair<string, double> obs in sta.Value)
                    x.Add(obs.Key);
                X.Add(sta.Key, x);
            }
            //var Lnew = new Dictionary<string, Dictionary<string, double>>(ObsL);
            int i = 0;
            foreach (KeyValuePair<string, List<string>> sta in X)
            {
                foreach (string obs in sta.Value)
                {
                    obsL[sta.Key][obs] = D2DMS(DMS2D(obsL[sta.Key][obs]) + A[i] / 3600);
                    i++;
                }
            }
        }
    }
    public class Rand
    {
        /// <summary>
        /// 生成随机数组
        /// </summary>
        /// <param name="count">产生随机数的次数</param>
        /// <param name="obs_num">观测值个数，每组随机数的个数</param>
        /// <param name="u">设计均值</param>
        /// <param name="d">设计中误差</param>
        /// <returns></returns>
        public static double[] GetRand(int count, int obs_num, double u, double d)
        {
            List<List<double>> B = new List<List<double>>();
            for (int p = 0; p < count; p++)
            {
                List<double> A = new List<double>();
                while (true)
                {
                    if (A.Count < obs_num)
                    {
                        double r = Rand1(u, d);
                        A.Add(r);
                    }
                    double std = Std(A.ToArray());
                    for (int i = 0; i < A.Count; i++)
                    {
                        if (A[i] > 2 * std)
                            A.Remove(A[i]);
                    }
                    if (A.Count == obs_num)
                        break;
                }
                B.Add(A);
            }
            double[] C = new double[obs_num];
            for (int p = 0; p < obs_num; p++)
            {
                double b = 0;
                for (int q = 0; q < count; q++)
                    b += B[q][p];
                C[p] = b / count;
            }
            return C;
        }

        public static double[] GetRand2(int count, int obs_num, double u, double d)
        {
            List<double> B = new List<double>();
            for (int p = 0; p < obs_num; p++)
            {
                List<double> A = new List<double>();
                while (A.Count < count)
                {
                    double r = Rand1(u, d);
                    A.Add(r);
                }
                double std = Std(A.ToArray());
                for (int i = 0; i < A.Count; i++)
                {
                    if (A[i] > 2 * std)
                        A.Remove(A[i]);
                }
                double sum = 0;
                for (int i = 0; i < A.Count; i++)
                {
                    sum += Math.Abs(A[i]);
                }
                double ave = sum / A.Count;
                Random rd = new Random();
                int b = rd.Next(0, 10);
                int symbol = b % 2;
                int sign = (int)Math.Pow(-1, symbol);
                double val = ave * sign;
                B.Add(val);
            }
            return B.ToArray();
        }
        
        //求均值
        static double Ave(double[] A)
        {
            double s = 0;
            for (int i = 0; i < A.Length; i++)
            {
                s += A[i];
            }
            return s / A.Length;
        }
        
        //求标准差
        static double Std(double[] A)
        {
            double s = 0;
            double ave = Ave(A);
            for (int i = 0; i < A.Length; i++)
            {
                s += Math.Pow(A[i] - ave, 2) / (A.Length - 1);
            }
            return Math.Sqrt(s);
        }
        
        //输入均值和中误差生成随机数
        static double Rand1(double u, double d)
        {
            double u1, u2, z;
            u1 = new Random().NextDouble();
            u2 = new Random().NextDouble();
            z = Math.Sqrt(-2 * Math.Log(u1)) * Math.Sin(2 * Math.PI * u2);
            return u + z * d;
        }
        
        //生成随机数
        static double Rand2(double u, double d)
        {
            double x = RNG();
            return u + x * d;
        }
        
        //生成标准正态分布的随机数
        static double RNG()
        {
            Random r1, r2;
            double v1, v2, rsq = 0, fac = 0;
            r1 = new Random(unchecked((int)DateTime.Now.Ticks));
            r2 = new Random(~unchecked((int)DateTime.Now.Ticks));
            double iset = 0, gset = 0;
            do
            {
                v1 = 2.0 * r1.NextDouble() - 1.0;
                v2 = 2.0 * r2.NextDouble() - 1.0;
                rsq = v1 * v1 + v2 * v2;
            } while (rsq >= 1.0 || rsq == 0.0);
            if (iset == 0)
            {
                fac = Math.Sqrt(-2.0 * Math.Log(rsq) / rsq);
                gset = v1 * fac;
                iset = 1;
                return v2 * fac;
            }
            else
            {
                iset = 0;
                return gset;
            }
        }
    }
}
